import { Disposable, Lifecycle, injectable, scoped, singleton } from "tsyringe";
import type { TimeoutID, IntervalID, ImmediateID } from 'timers'
export interface TimerCallback {
    (args: void): void
}
@scoped(Lifecycle.ContainerScoped)
export class Timer implements Disposable {
    private setTimeoutHandlers: any[] = [];
    private setIntervalHandlers: any[] = [];
    private setImmediateHandlers: any[] = [];
    setTimeout(fn: TimerCallback, timeout: number = 300) {
        const timer = setTimeout(fn, timeout);
        this.setTimeoutHandlers.push(timer)
        return timer;
    }
    clearTimeout(handler: TimeoutID) {
        if(!handler) return;
        clearTimeout(handler)
        this.setTimeoutHandlers = this.setTimeoutHandlers.filter(it => it !== handler)
    }

    setInterval(fn: TimerCallback, timeout: number = 300) {
        const timer = setInterval(fn, timeout);
        this.setIntervalHandlers.push(timer)
        return timer;
    }
    clearInterval(handler: IntervalID) {
        if(!handler) return;
        clearInterval(handler)
        this.setIntervalHandlers = this.setIntervalHandlers.filter(it => it !== handler)
    }

    setImmediate(listener: any, ...args: any[]) {
        const timer = setImmediate(listener, ...args);
        this.setImmediateHandlers.push(timer)
        return timer;
    }
    clearImmediate(handler: ImmediateID) {
        if(!handler) return;
        clearImmediate(handler)
        this.setImmediateHandlers = this.setImmediateHandlers.filter(it => it !== handler)
    }
    dispose(): void | Promise<void> {
        this.setTimeoutHandlers.map(handler => this.clearTimeout(handler))
        this.setIntervalHandlers.map(handler => this.clearInterval(handler))
        this.setImmediateHandlers.map(handler => this.clearImmediate(handler))
        log(`timer clear finish`)
    }
}